package org.lemon.cla.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.lemon.cla.enums.HttpStatusEnum;
import org.lemon.cla.dto.response.ResponseResult;
import org.lemon.cla.dto.request.ClubMemberCreateRequest;
import org.lemon.cla.dto.request.ClubMemberUpdateRequest;
import org.lemon.cla.dto.request.ClubMemberSearchRequest;
import org.lemon.cla.exception.BusinessException;
import org.lemon.cla.pojo.ClubMember;
import org.lemon.cla.enums.ClubMemberRoleEnum;
import org.lemon.cla.enums.ClubMemberStatusEnum;
import org.lemon.cla.pojo.User; // Import User entity
import org.lemon.cla.vo.ClubMemberVo; // Import ClubMemberVo
import org.lemon.cla.service.IClubMemberService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;

import java.time.LocalDateTime;
import java.util.Optional; // Import Optional


@RestController
@RequestMapping("/api/club-members")
@Tag(name = "社团成员管理", description = "提供社团成员信息的 CRUD 和查询接口")
public class ClubMemberController {

    @Autowired
    private IClubMemberService clubMemberService;

    @Operation(summary = "获取所有社团成员", description = "分页获取所有社团成员列表，**包含成员用户信息 (若用户被逻辑删除则显示为未知)**")
    @GetMapping
    public ResponseResult<IPage<ClubMemberVo>> getAllClubMembers( // 返回类型 ClubMemberVo
                                                                  @Parameter(description = "页码", example = "1") @RequestParam(defaultValue = "1") Integer pageNum,
                                                                  @Parameter(description = "每页数量", example = "10") @RequestParam(defaultValue = "10") Integer pageSize) {
        Page<ClubMemberVo> page = new Page<>(pageNum, pageSize);
        IPage<ClubMemberVo> memberPage = clubMemberService.getAllClubMembersVo(page); // 调用 Service 层新方法
        return ResponseResult.success(HttpStatusEnum.SUCCESS.getCode(), HttpStatusEnum.SUCCESS.getMessage(), memberPage);
    }

    @Operation(summary = "根据ID获取社团成员", description = "根据成员ID获取社团成员详情，**包含成员用户信息 (若用户被逻辑删除则显示为未知)**")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成功获取成员"),
            @ApiResponse(responseCode = "404", description = "成员未找到")
    })
    @GetMapping("/{id}")
    public ResponseResult<ClubMemberVo> getClubMemberById( // 返回类型 ClubMemberVo
                                                           @Parameter(description = "成员ID", required = true, example = "1") @PathVariable Long id) {
        // 使用Optional简化null检查，如果未找到则抛出异常
        return Optional.ofNullable(clubMemberService.getClubMemberVoById(id)) // 调用 Service 层新方法
                .map(memberVo -> ResponseResult.success(HttpStatusEnum.SUCCESS.getCode(), HttpStatusEnum.SUCCESS.getMessage(), memberVo))
                .orElseThrow(() -> new BusinessException(HttpStatusEnum.NOT_FOUND.getCode(), "成员未找到。")); // 抛出异常
    }

    @Operation(summary = "创建新社团成员", description = "创建一个新的社团成员记录 (需校验联合唯一约束)")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "201", description = "成员创建成功"),
            @ApiResponse(responseCode = "400", description = "请求参数错误 (如校验失败)"),
            @ApiResponse(responseCode = "409", description = "用户已是该社团成员"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PostMapping
    @PreAuthorize("isAuthenticated()") // 只有认证用户才能创建社团成员关系 (如申请加入)
    public ResponseResult<ClubMember> createClubMember(
            @Parameter(description = "社团成员创建请求对象 (无需传入 memberId, joinTime, status)", required = true)
            @RequestBody @Valid ClubMemberCreateRequest request) {

        // 联合唯一约束校验：检查该用户是否已是该社团成员
        if (clubMemberService.isMemberExists(request.getUserId(), request.getClubId())) {
            throw new BusinessException(HttpStatusEnum.CONFLICT.getCode(), "用户已是该社团成员，无法重复添加。"); // 抛出异常
        }

        ClubMember clubMember = new ClubMember();
        BeanUtils.copyProperties(request, clubMember);

        // 自动设置加入时间和默认状态
        clubMember.setJoinTime(LocalDateTime.now());
        clubMember.setStatus(ClubMemberStatusEnum.APPLYING); // 默认新成员状态为“申请中”

        boolean success = clubMemberService.save(clubMember);
        if (!success) { // 如果保存操作返回false但未抛出异常
            throw new BusinessException(HttpStatusEnum.BAD_REQUEST.getCode(), "社团成员创建失败，请稍后重试。"); // 抛出异常
        }
        return ResponseResult.success(HttpStatusEnum.CREATED.getCode(), HttpStatusEnum.CREATED.getMessage(), clubMember);
    }

    @Operation(summary = "更新社团成员信息", description = "根据成员ID更新社团成员信息 (如角色、状态)")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成员更新成功"),
            @ApiResponse(responseCode = "400", description = "请求参数错误"),
            @ApiResponse(responseCode = "404", description = "成员未找到"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PutMapping("/{id}")
    @PreAuthorize("hasRole('管理员')") // 只有拥有 'ROLE_管理员' 角色的用户才能访问
    public ResponseResult<ClubMember> updateClubMember(
            @Parameter(description = "成员ID", required = true, example = "1") @PathVariable Long id,
            @Parameter(description = "更新后的社团成员对象", required = true) @RequestBody @Valid ClubMemberUpdateRequest request) {

        // 校验成员是否存在
        ClubMember existingMember = Optional.ofNullable(clubMemberService.getById(id))
                .orElseThrow(() -> new BusinessException(HttpStatusEnum.NOT_FOUND.getCode(), "成员未找到。")); // 抛出异常


        BeanUtils.copyProperties(request, existingMember);

        boolean success = clubMemberService.updateById(existingMember);
        if (!success) { // 如果更新返回false
            throw new BusinessException(HttpStatusEnum.BAD_REQUEST.getCode(), "成员更新失败，请稍后重试。"); // 抛出异常
        }
        return ResponseResult.success(HttpStatusEnum.SUCCESS.getCode(), HttpStatusEnum.SUCCESS.getMessage(), existingMember);
    }

    @Operation(summary = "删除社团成员", description = "根据成员ID删除社团成员。")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "204", description = "成员删除成功"),
            @ApiResponse(responseCode = "404", description = "成员未找到"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @DeleteMapping("/{id}")
    @PreAuthorize("hasRole('管理员')") // 只有拥有 'ROLE_管理员' 角色的用户才能访问
    public ResponseResult<Void> deleteClubMember(
            @Parameter(description = "成员ID", required = true, example = "1") @PathVariable Long id) {
        boolean success = clubMemberService.removeById(id);
        if (!success) { // 如果删除返回false
            throw new BusinessException(HttpStatusEnum.BAD_REQUEST.getCode(), "成员未找到或删除失败。"); // 抛出异常
        }
        return ResponseResult.success(HttpStatusEnum.NO_CONTENT.getCode(), HttpStatusEnum.NO_CONTENT.getMessage(), null);
    }

    @Operation(summary = "模糊查询社团成员(查询首选)", description = "根据用户ID、社团ID、角色、状态、加入时间范围进行模糊查询，**返回包含成员用户信息的视图对象 (若用户被逻辑删除则显示为未知)**")
    @PostMapping("/search")
    public ResponseResult<IPage<ClubMemberVo>> searchClubMembers( // 返回 ClubMemberVo
                                                                  @Parameter(description = "页码", example = "1") @RequestParam(defaultValue = "1") Integer pageNum,
                                                                  @Parameter(description = "每页数量", example = "10") @RequestParam(defaultValue = "10") Integer pageSize,
                                                                  @Parameter(description = "社团成员查询请求对象", required = true) @RequestBody ClubMemberSearchRequest request) {

        Page<ClubMemberVo> page = new Page<>(pageNum, pageSize); // 泛型改为 ClubMemberVo

        // 使用Optional简化，确保request总是一个非null的实例
        request = Optional.ofNullable(request).orElseGet(ClubMemberSearchRequest::new);

        IPage<ClubMemberVo> resultPage = clubMemberService.searchClubMembersByConditions(page, request);

        return ResponseResult.success(HttpStatusEnum.SUCCESS.getCode(), HttpStatusEnum.SUCCESS.getMessage(), resultPage);
    }

    @Operation(summary = "设置社团成员角色", description = "根据成员ID设置社团成员的角色（成员、社长）")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "角色设置成功"),
            @ApiResponse(responseCode = "400", description = "请求参数错误或角色值无效"),
            @ApiResponse(responseCode = "404", description = "成员未找到"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PutMapping("/{id}/role/{newRoleStr}")
    @PreAuthorize("hasRole('管理员')") // 只有拥有 'ROLE_管理员' 角色的用户才能访问
    public ResponseResult<Void> setClubMemberRole(
            @Parameter(description = "成员ID", required = true, example = "1") @PathVariable Long id,
            @Parameter(description = "新的社团内角色", required = true, example = "社长", schema = @Schema(implementation = ClubMemberRoleEnum.class))
            @PathVariable String newRoleStr) {

        // 转换枚举，如果无效则 fromDescription 抛出异常，由GlobalExceptionHandler处理
        ClubMemberRoleEnum newRole = ClubMemberRoleEnum.fromDescription(newRoleStr);

        boolean success = clubMemberService.updateMemberRole(id, newRole);
        if (!success) { // 如果更新返回false
            throw new BusinessException(HttpStatusEnum.BAD_METHOD.getCode(), "成员未找到或角色设置失败。"); // 抛出异常
        }
        return ResponseResult.success(HttpStatusEnum.SUCCESS.getCode(), "社团成员角色设置成功", null);
    }

    @Operation(summary = "设置社团成员状态", description = "根据成员ID设置社团成员的状态（申请中、已加入、已拒绝）")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "状态设置成功"),
            @ApiResponse(responseCode = "400", description = "请求参数错误或状态值无效"),
            @ApiResponse(responseCode = "404", description = "成员未找到"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PutMapping("/{id}/status/{newStatusStr}")
    @PreAuthorize("hasRole('管理员')") // 只有拥有 'ROLE_管理员' 角色的用户才能访问
    public ResponseResult<Void> setClubMemberStatus(
            @Parameter(description = "成员ID", required = true, example = "1") @PathVariable Long id,
            @Parameter(description = "新的社团成员状态", required = true, example = "已加入", schema = @Schema(implementation = ClubMemberStatusEnum.class))
            @PathVariable String newStatusStr) {

        // 转换枚举，如果无效则 fromDescription 抛出 IllegalArgumentException，由GlobalExceptionHandler处理
        ClubMemberStatusEnum newStatus = ClubMemberStatusEnum.fromDescription(newStatusStr);

        boolean success = clubMemberService.updateMemberStatus(id, newStatus);
        if (!success) { // 如果更新返回false
            throw new BusinessException(HttpStatusEnum.BAD_REQUEST.getCode(), "成员未找到或状态设置失败。"); // 抛出异常
        }
        return ResponseResult.success(HttpStatusEnum.SUCCESS.getCode(), "社团成员状态设置成功", null);
    }

    @Operation(summary = "用户退出社团", description = "根据社团ID退出对应的社团成员关系，只有成员本人可以通过请求头中的Token操作")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成功退出社团"),
            @ApiResponse(responseCode = "401", description = "未授权，请提供有效的Token"),
            @ApiResponse(responseCode = "403", description = "权限不足，无法获取当前用户ID或操作他人成员关系"),
            @ApiResponse(responseCode = "404", description = "该社团或对应的成员关系未找到"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @DeleteMapping("/withdraw/{clubId}") // DELETE 方法，通过 clubId 退出
    @PreAuthorize("isAuthenticated()") // 确保用户已登录
    public ResponseResult<Void> withdrawFromClub(
            @Parameter(description = "要退出的社团ID", required = true, example = "1") @PathVariable Long clubId,
            @AuthenticationPrincipal User currentUser) { // 获取当前登录的用户对象

        // 校验当前用户是否有效
        Long currentUserId = Optional.ofNullable(currentUser)
                .map(User::getUserId)
                .map(Long::valueOf) // 转换为Long
                .orElseThrow(() -> new BusinessException(HttpStatusEnum.NOT_FOUND.getCode(), "无法获取当前登录用户ID。")); // 抛出异常

        boolean success = clubMemberService.withdrawFromClub(currentUserId, clubId);
        if (!success) {
            // 如果退出失败，进一步判断原因
            // 依赖Service层的isMemberExists判断，如果Service返回false且成员关系不存在，则抛出未找到异常
            Optional.of(clubMemberService.isMemberExists(currentUserId, clubId))
                    .filter(exists -> exists) // 如果存在（但 Service 返回false），说明是其他内部错误
                    .ifPresentOrElse(
                            exists -> { throw new BusinessException(HttpStatusEnum.BAD_METHOD.getCode(), "退出社团失败，请稍后重试。"); }, // 如果 exists 为 true，表示成员关系存在但删除失败
                            () -> { throw new BusinessException(HttpStatusEnum.BAD_REQUEST.getCode(), "当前用户不是该社团成员或成员关系已不存在。"); } // 如果 exists 为 false，表示成员关系不存在
                    );
        }
        return ResponseResult.success(HttpStatusEnum.SUCCESS.getCode(), "成功退出社团", null);
    }
}